#include "rtc_func.h"
#include "own_chip_rtc.h"
#include "print_rtt.h"
static uint8_t bin2bcd(uint8_t bin) { return ((bin / 10) << 4) | (bin % 10); }
static uint8_t bcd2bin(uint8_t bcd) { return ((bcd >> 4) * 10) + (bcd & 0x0F); }
/* 读取原始寄存器，共 7 字节：VL_SEC~YEAR */
static int rtc_read_raw(uint8_t *buf)
{
  if (1 == i2c_read_bytes(buf, 0xA2, REG_VL_SEC, 8, 7))
  {
    return 0;
  }
  return -1;
}
/* 写整个时钟寄存器（7 字节） */
static int rtc_write_raw(uint8_t *buf)
{
  if (1 == i2c_write_bytes(buf, 0xA2, REG_VL_SEC, 8, 7))
  {
    return 0;
  }
  return -1;
}

static int rtc_time_is_valid(time_t *t)
{
  time_t now;
  if (get_compile_time(&now) != 0)
  {
    return 0;
  }
  LOG_INFO("Compile time_t: %d\n", now);
  LOG_INFO("rtc time_t: %d\n", *t);

  if (((*t) < now) || ((*t) > (now + 630720000)))
  {
    *t = now;
    LOG_ERROR("RTC time is invalid, set to compile time\r");
    return 0;
  }
  return 1;
}
/* 把 BCD 寄存器解析成结构体 */
static void raw2time(const uint8_t *raw, struct tm *t)
{
  t->tm_sec = bcd2bin(raw[0] & 0x7F);
  t->tm_min = bcd2bin(raw[1] & 0x7F);
  t->tm_hour = bcd2bin(raw[2] & 0x3F);
  t->tm_mday = bcd2bin(raw[3] & 0x3F);
  t->tm_wday = bcd2bin(raw[4] & 0x07);
  t->tm_mon = bcd2bin(raw[5] & 0x1F) - 1;
  t->tm_year = (bcd2bin(raw[6]) + 100);
  t->tm_isdst = -1;
}

/* 把结构体打包成 BCD 寄存器 */
static void time2raw(const struct tm *t, uint8_t *raw)
{
  raw[0] = bin2bcd(t->tm_sec);
  raw[1] = bin2bcd(t->tm_min);
  raw[2] = bin2bcd(t->tm_hour);
  raw[3] = bin2bcd(t->tm_mday);
  raw[4] = bin2bcd(t->tm_wday);

  /* 月 BCD + 世纪位 1 */
  raw[5] = (bin2bcd(t->tm_mon + 1) | 0x80);
  raw[6] = bin2bcd((t->tm_year - 100));
}
int RTC_Chip_Get_Time(struct tm *t)
{
  uint8_t raw[7];
  int vl_flag;
  /* 1. 读时钟寄存器 */
  if (rtc_read_raw(raw) != 0)
  {
    return -1;
  }
  /* 2. 检查 VL 位（OSC 停振） */
  vl_flag = (raw[0] >> 7) & 1;
  if (vl_flag == 1)
  {
    return -2;
  }
  /* 3. 解析当前时间 */
  raw2time(raw, t);
  return 0;
}
int RTC_Chip_Set_Time(const struct tm *t)
{
  uint8_t raw[7], REG_CTRL1_STATUS, ret;
  time2raw(t, raw);
  REG_CTRL1_STATUS = 0x80;
  ret = i2c_write_bytes(&REG_CTRL1_STATUS, 0xA2, REG_CTRL1, 8, 1);
  if (ret != 1)
  {
    return -1;
  }
  /* 2. 写 7 字节时间 */
  raw[0] &= 0x7F; // 确保 VL=0
  if (0 != rtc_write_raw(raw))
  {
    return -1;
  }
  /* 3. 重新起跑 */
  REG_CTRL1_STATUS = 0x00;
  ret = i2c_write_bytes(&REG_CTRL1_STATUS, 0xA2, REG_CTRL1, 8, 1);
  if (ret != 1)
  {
    return -1;
  }
  return 0;
}
// 月份名称到数字的映射
static const char *month_names[] = {
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

int get_compile_time(time_t *ticks)
{
  const char *compile_date = __DATE__; // "Mmm dd yyyy"
  const char *compile_time = __TIME__; // "hh:mm:ss"
  struct tm tm_info = {0};
  int i;
  char temp[4]; // 用于存储月份缩写

  // 1. 解析月份 (Mmm)
  strncpy(temp, compile_date, 3);
  temp[3] = '\0';
  tm_info.tm_mon = -1;
  for (i = 0; i < 12; i++)
  {
    if (strcmp(temp, month_names[i]) == 0)
    {
      tm_info.tm_mon = i;
      break;
    }
  }
  if (tm_info.tm_mon == -1)
  {
    return -1; // 无效月份
  }

  // 2. 解析日期 (dd)
  // 注意：日期前面可能有一个空格（如 " 5"），需要处理
  tm_info.tm_mday = (compile_date[4] == ' ') ? (compile_date[5] - '0') : ((compile_date[4] - '0') * 10 + (compile_date[5] - '0'));

  // 3. 解析年份 (yyyy)
  tm_info.tm_year = (compile_date[7] - '0') * 1000 +
                    (compile_date[8] - '0') * 100 +
                    (compile_date[9] - '0') * 10 +
                    (compile_date[10] - '0') - 1900; // tm_year 是从1900开始的

  // 4. 解析小时 (hh)
  tm_info.tm_hour = (compile_time[0] - '0') * 10 + (compile_time[1] - '0');

  // 5. 解析分钟 (mm)
  tm_info.tm_min = (compile_time[3] - '0') * 10 + (compile_time[4] - '0');

  // 6. 解析秒 (ss)
  tm_info.tm_sec = (compile_time[6] - '0') * 10 + (compile_time[7] - '0');

  // 7. 填充其他必要字段
  tm_info.tm_isdst = -1; // 让mktime自行判断夏令时

  // 8. 转换为 time_t
  *ticks = mktime(&tm_info);
  if (*ticks == (time_t)(-1))
  {
    return -1; // mktime失败
  }

  return 0;
}

int RTC_Chip_init(void)
{
  uint8_t raw[7];
  struct tm now, *now_p;
  int vl_flag;

  /* 1. 读时钟寄存器 */
  if (rtc_read_raw(raw) == 0)
  {
    LOG_INFO("read raw success!\n");
  }
  else
  {
    LOG_ERROR("read raw error!\n");
    return -1;
  }
  /* 2. 检查 VL 位（OSC 停振） */
  vl_flag = ((raw[0] >> 7) & 1);
  LOG_INFO("vl_flag=%d\n", vl_flag); // 打印VL位
  /* 3. 解析当前时间 */
  raw2time(raw, &now);
  LOG_INFO("read rtc time:%d-%d-%d %d:%d:%d\n", now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec);
  device_time_tickets = mktime(&now);
  /* 4. 若 VL=1 或时间不合理，则写入编译时间 */
  if (vl_flag || (!rtc_time_is_valid(&device_time_tickets)))
  {

    now_p = localtime(&device_time_tickets);
    LOG_INFO("write complie time to rtc:,:%d-%d-%d %d:%d:%d\n", now_p->tm_year + 1900,
             now_p->tm_mon + 1, now_p->tm_mday, now_p->tm_hour, now_p->tm_min, now_p->tm_sec);
    if (RTC_Chip_Set_Time(now_p) != 0)
    {
      return -1;
    }
  }
  TIM1_Init_1ms();
  device_time_ms_tickets = ((uint64_t)device_time_tickets) * 1000;
  return RTC_Chip_init_1hour_timer_int(); /* 一切 OK */
}
int RTC_Chip_init_1hour_timer_int(void)
{
  int ret;
  uint8_t REG_CTRL2_STATUS, TIMER_CTRL_STATUS, TIMER_VALUE;

  // 1. 配置REG_CTRL_STATUS2：启用定时器中断（TIE=1），清除旧中断标志（TF=0）
  // 0x01：Bit0(TIE)=1（定时器中断使能），Bit2(TF)=0（清标志），其余位按文档写0
  REG_CTRL2_STATUS = 0x01;
  ret = i2c_write_bytes(&REG_CTRL2_STATUS, 0xA2, REG_CTRL2, 8, 1);
  if (ret != 1)
    return -1;

  // 2. 配置REG_TIMER_CTRL：启用定时器（TE=1），选1/60Hz源时钟（TD[1:0]=11）
  // 0x83：Bit7(TE)=1（定时器使能），Bit1-0(TD)=11（1/60Hz，周期60秒）
  TIMER_CTRL_STATUS = 0X83;
  ret = i2c_write_bytes(&TIMER_CTRL_STATUS, 0xA2, 0x0E, 8, 1);
  if (ret != 1)
    return -1;

  // 3. 配置REG_TIMER_VALUE：倒计数数值=1（1×60秒=60秒，即1分钟）
  TIMER_VALUE = 0X3C;
  ret = i2c_write_bytes(&TIMER_VALUE, 0xA2, 0x0F, 8, 1);
  if (ret != 1)
    return -1;

  return 0;
}
int RTC_Chip_Timer_int_handler(void)
{
  uint8_t ctrl_status2, timer_value;
  uint8_t raw[7];
  struct tm now, *now_p;
  int vl_flag;
  // 假设已实现I2C单字节读函数（符合9.5节协议）

  // 1. 读取寄存器确认中断源（TF=1：定时器中断）
  if (1 != i2c_read_bytes(&ctrl_status2, 0xA2, REG_CTRL2, 8, 1))
    return -1;
  if ((ctrl_status2 & 0x04U) == 0) // Bit2(TF)=1表示定时器中断触发
  {
    LOG_ERROR("not TF Triggered!\n");
    return -1;
  }

  // 2. 用户自定义：每分钟中断执行的任务（如IO翻转、数据记录等）
  LOG_COLOR(YELLOW, "RTC Timer Interrupt Triggered!\n");
  /* 1. 读时钟寄存器 */
  if (rtc_read_raw(raw) == 0)
  {
    LOG_INFO("read raw success!\n");
  }
  else
  {
    LOG_ERROR("read raw error!\n");
    return -1;
  }
  /* 2. 检查 VL 位（OSC 停振） */
  vl_flag = ((raw[0] >> 7) & 1);
  LOG_INFO("vl_flag=%d\n", vl_flag); // 打印VL位
  /* 3. 解析当前时间 */
  raw2time(raw, &now);
  device_time_tickets = mktime(&now);
  /* 4. 若 VL=1 或时间不合理，则写入编译时间 */
  if (vl_flag || (!rtc_time_is_valid(&device_time_tickets)))
  {

    now_p = localtime(&device_time_tickets);
    LOG_INFO("write complie time to rtc:,:%d-%d-%d %d:%d:%d\n", now_p->tm_year + 1900,
             now_p->tm_mon + 1, now_p->tm_mday, now_p->tm_hour, now_p->tm_min, now_p->tm_sec);
    if (RTC_Chip_Set_Time(now_p) != 0)
    {
      return -1;
    }
  }
  device_time_ms_tickets = ((uint64_t)device_time_tickets) * 1000;
  // 3. 清除定时器中断标志（写0到TF位，保持TIE=1）
  ctrl_status2 = 0x01;
  if (1 != i2c_write_bytes(&ctrl_status2, 0xA2, REG_CTRL2, 8, 1))
    return -1;
  timer_value = 0X3C;
  if (1 != i2c_write_bytes(&timer_value, 0xA2, 0x0F, 8, 1))
    return -1;
  return 0;
}
void PC7_Exti_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  EXTI_InitTypeDef EXTI_InitStruct;
  NVIC_InitTypeDef NVIC_InitStruct;

  // 使能GPIO C和SYSCFG时钟
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  // 配置PC7为上拉输入（适配INT开漏输出，避免电平悬浮）
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_Init(GPIOC, &GPIO_InitStruct);

  // 连接PC7到EXTI7
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource7);

  // 配置EXTI7：下降沿触发（INT从高变低时触发中断）
  EXTI_InitStruct.EXTI_Line = EXTI_Line7;
  EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
  EXTI_InitStruct.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStruct);

  // 配置NVIC：使能EXTI7中断
  NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn; // PC7归属EXTI9_5_IRQn
  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStruct);
}
